from  flask_classy import FlaskView, route
from flask import request
from ..schema.param import local_auth_schema
from ..models.auth import LocalAuth, AuthHistory
from ..models.member import Member
from ..schema.error import LOGIN_NAME_EXIST, PARAMS_DOES_NOT_EXIST, LOCAL_AUTH_NOT_EXIST, INCORRECT_PASSWORD, \
    PARAMS_ERROR ,AUTH_NOT_EXIST
from ..models.account import Account
from ..schema.object import success_schema, member_schema
from marshmallow.exceptions import ValidationError
import datetime
import redis
from . import jsonify_with_success

class AuthsView(FlaskView):
    _access_token_store = None

    @classmethod
    def get_member_info(cls, access_token):
        member_info = cls._access_token_store.get(access_token)
        if member_info:
            member_info = member_schema.loads(member_info.decode('utf-8')).data
            member = Member.get_or_none(Member.id == member_info.get('id'))
            return member
        return None

    @route('/<access_token>')
    def fetch_access_token(self, access_token):
        member = AuthsView._access_token_store.get(access_token)
        if not member:
            return AUTH_NOT_EXIST.jsonify()
        return jsonify_with_success(member_schema.loads(member.decode('utf-8')).data)

    @route('/local/login', methods=['POST'])
    def local_login(self):
        if request.data:
            try:
                params, errors = local_auth_schema.loads(request.data.decode(request.charset))
            except ValidationError as etx:
                return PARAMS_ERROR.jsonify(etx)
            login_name = params.get('login_name')
            password = params.get('password')
            local_auth = LocalAuth.get_or_none(LocalAuth.login_name == login_name)
            if not local_auth:
                return LOCAL_AUTH_NOT_EXIST.jsonify()
            if not local_auth.verify_password(password):
                local_auth.retry_count += 1
                local_auth.save()
                return INCORRECT_PASSWORD.jsonify()
            local_auth.retry_count = 0
            local_auth.save()
            return self._login(local_auth.member)
        else:
            return PARAMS_DOES_NOT_EXIST.jsonify()

    @route('/local/create', methods=['POST'])
    def local_auth(self):
        if request.data:
            try:
                params, errors = local_auth_schema.loads(request.data.decode(request.charset))

            except ValidationError as  etx:
                return PARAMS_ERROR.jsonify(etx)

            login_name = params.get('login_name')

            if LocalAuth.exist(login_name):
                return LOGIN_NAME_EXIST.jsonify()
            password = params.get('password')
            # from hashlib import sha1
            # sha1.update(password)
            # password = sha1.hexdisget()
            member = self._create_member(email=login_name)
            LocalAuth.create(**{
                'login_name': login_name,
                'password': password,
                'member': member,
                'updated_at': datetime.datetime.now()
                # 'last_login_at': datetime.datetime.now(),
                # 'last_login_ip': request.remote_addr
            })
            return self._login(member)
        else:
            return
            PARAMS_DOES_NOT_EXIST.jsonify()

    def _create_access_token(self, key):
        import hashlib
        sha1 = hashlib.sha1()
        sha1.update(key.encode())
        return sha1.hexdigest()

    def _login(self, member, **args):
        import time
        access_token = self._create_access_token('{}-{}'.format(time.time(), member.secret_key))

        member_data = member_schema.dump(member).data
        from ..extensions import get_ip_country_and_city
        country_and_city = get_ip_country_and_city(request.remote_addr)
        # 需要根据语言还获取
        if country_and_city:
            country = country_and_city[0].names('zh-CN')
            city = country_and_city[1].names['zh-CN']
        else:
            country = '未知'
            city = '未知'
        AuthHistory.create(**{
            'member': member,
            'login_ip': request.remote_addr,
            'country': country,
            'city': city,
            'platform': args.get('platform', 'web'),
            'platform_identify': args.get('identify', None),
            'access_token': access_token
        })
        AuthsView._access_token_store.setex(access_token,100000,member_data)
        # AuthsView._access_token_store.set(access_token, member_data)

        return success_schema.jsonify({
            'access_token': access_token,
            'member': member_data
        })

    def _create_account(self, member):
        from ..database import next_id
        return Account.create(**{
            'member': member,
            'id':   str(next_id()).zfill(24),
            'currency': member.currency,
            'updated_at': datetime.datetime.now()

        })

    def _create_member(self, **kwargs):
        if not kwargs.get('currency'):
            from ..models.currency import Currency
            kwargs['currency'] = Currency.get_main_currency()
        if not kwargs.get('screen_name'):
            import random
            kwargs['screen_name'] = 'vsouser{}'.format(random.randint(1000, 99999))
        if not kwargs.get('head_image'):
            from ..models.setting import Setting
            kwargs['head_image'] = Setting.get_setting('DEFAULT_HEAD_IMAGE')

        kwargs['updated_at'] = datetime.datetime.now()
        if not kwargs.get('country'):
            from ..extensions import get_ip_country_and_city
            country_and_city = get_ip_country_and_city(request.remote_addr)
            if country_and_city is not None:
                kwargs['country'] = country_and_city(0)
            else:
                from ..models.country import Country
                kwargs['country'] = Country.get(Country.id == 'CN')
        from ..database import next_id

        member = Member.create(**kwargs)
        # 创建资金账户
        self._create_account(member)
        return member

    @classmethod
    def register(cls, app, **kwargs):
        print('register')
        access_token_store_url = app.config.get('ACCESS_TOKEN_STORE_URL', None)
        cls._access_token_store = redis.StrictRedis.from_url(access_token_store_url)
        super().register(app, **kwargs)
